import {CoverageRate, CoverageParser} from '../test-parser'
import {checkCoverageFileExist, readFile} from '../utils'
import * as step from '@flow-step/step-toolkit'
import * as cheerio from 'cheerio'

export class JaCoCoParser implements CoverageParser {
    async parse(path: string): Promise<CoverageRate> {
        step.info(`Parsing JaCoCo Html report: ${path}`)
        const htmlContent = await readFile(path)
        step.debug(`htmlContent: ${htmlContent}`)
        return this.count(htmlContent);
    }

    async count(htmlContent: string): Promise<CoverageRate>{
        const $ = cheerio.load(htmlContent)
        let res = {
            lineCoverageRate: 0,
            branchCoverageRate: 0,
            methodCoverageRate: 0,
            classCoverageRate: 0,
            instructionCoverageRate: 0
        } as CoverageRate

        const coverageTable = $("table.coverage");
        if (coverageTable.length === 0) {
            throw new Error("No coverage table found in the HTML content.");
        }

        // Instruction Coverage
        const instructionData =  $(`table.coverage tfoot tr td`).eq(1).text().replace(/,/g, '');
        const regex = /[,\d]+ of [,\d]+/;
        if (regex.test(instructionData)) {
            const [missed, total] = instructionData.split(' of ').map((val) => parseInt(val.replace(/,/g, ''), 10));
            const hit = total - missed;
            res.instructionCoverageRate = total !== 0 ? parseFloat(((hit / total) * 100).toFixed(2)) : 0;
        }

        // Branch Coverage
        const branchData = $(`table.coverage tfoot tr td`).eq(3).text().replace(/,/g, '');
        if (regex.test(branchData)) {
            const [missed, total] = branchData.split(' of ').map((val) => parseInt(val.replace(/,/g, ''), 10));
            const hit = total - missed;
            res.branchCoverageRate = total !== 0 ? parseFloat(((hit / total) * 100).toFixed(2)) : 0;
        }

        const extractValue = (index: number): number => {
            const text = $(`table.coverage tfoot tr td`).eq(index).text().replace(/,/g, '');
            return parseInt(text, 10) || 0;
        };

        // Line Coverage
        const lineTotal = extractValue(8);
        const lineMissed = extractValue(7);
        const lineHit = lineTotal - lineMissed;
        res.lineCoverageRate = lineTotal !== 0 ? parseFloat(((lineHit / lineTotal) * 100).toFixed(2)) : 0;

        // Method Coverage
        const methodTotal = extractValue(10);
        const methodMissed = extractValue(9);
        const methodHit = methodTotal - methodMissed;
        res.methodCoverageRate = methodTotal !== 0 ? parseFloat(((methodHit / methodTotal) * 100).toFixed(2)) : 0;

        // Class Coverage
        const classTotal = extractValue(12);
        const classMissed = extractValue(11);
        const classHit = classTotal - classMissed;
        res.classCoverageRate = classTotal !== 0 ? parseFloat(((classHit / classTotal) * 100).toFixed(2)) : 0;

        return res;
    }
}